<template>
  <div>
    <el-upload
      ref="elUpload"
      class="vupload"
      multiple
      :action="action"
      :file-list="fileList"
      :list-type="listType"
      :show-file-list="true"
      :on-success="handleSuccess"
      :on-remove="handelRemove"
      :on-error="handleError"
      :before-upload="beforeUpload"
      :on-preview="handlePreview"
      :data="extData"
    >
      <i class="el-icon-plus" v-if="listType === 'picture-card'"></i>
      <el-button size="small" type="primary" v-else>上传</el-button>

      <div slot="tip" class="el-upload__tip" v-if="tip">{{ tip }}</div>
    </el-upload>
    <el-dialog title="图片详情" :visible.sync="dialogVisible" append-to-body>
      <el-row type="flex" justify="center">
        <img :src="currentImg" alt class="preview-img" />
      </el-row>
    </el-dialog>
  </div>
</template>

<script>
import imgUtil from '@/utils/img';

export default {
  name: 'VUpload',
  props: {
    value: {
      type: Array,
      default() {
        return [];
      },
    },
    name: {
      type: String,
      default: 'file',
    },
    action: {
      type: String,
      default: '/api/file/upload',
    },
    fileSize: {
      type: Number,
      default: 20,
    },
    fileType: {
      type: Array,
      default() {
        return [];
      },
    },
    listType: {
      type: String,
      default: 'picture-card',
    },
    tip: {
      type: String,
      default: '',
    },
  },
  data() {
    return {
      fileList: [],
      extData: {},
      loading: false,
      currentImg: '',
      dialogVisible: false,
    };
  },
  watch: {
    value: {
      handler(val) {
        this.fileList = val || [];
      },
      immediate: true,
      deep: true,
    },
    fileList: {
      handler(val) {
        this.$emit('input', val);
      },
      deep: true,
    },
  },
  methods: {
    closeLoading() {
      this.loading = false;
    },
    handleSuccess(res, file) {
      this.closeLoading();
      const { status, data, msg } = res;
      if (status === 1) {
        file.id = data;

        if (data.fid) {
          file.id = data.fid;

          this.$emit('parse', data.summary || '');
        }
      } else {
        this.$message.error(msg || '图片上传出错，请稍后重试！');
      }

      this.fileList.push(file);
    },
    handleError(err) {
      this.$message.error(err.message || '图片上传失败，请稍后重试！');
    },
    beforeUpload(file) {
      const { fileSize, fileType, listType } = this;
      const isFileType = fileType && fileType.length ? fileType.indexOf(file.type) > -1 : true;
      const isLtSize = file.size / 1024 / 1024 <= fileSize;
      let flag = false;
      const self = this;

      if (!isFileType) {
        this.$message.error('上传文件格式错误!');
      }

      if (!isLtSize) {
        const unit = fileSize < 1 ? `${fileSize * 1000}KB` : `${fileSize}MB`;
        this.$message.error(`上传文件大小不能超过${unit}!`);
      }

      flag = isFileType && isLtSize;

      if (!flag) {
        return flag;
      }
      if (listType !== 'picture-card') {
        this.loading = true;
        return flag;
      }
      const { uploadFiles } = self.$refs.elUpload;
      const currentFileIndex = uploadFiles.findIndex(item => item.uid === file.uid);
      const currentFile = uploadFiles[currentFileIndex];

      this.loading = true;
      return new Promise(resolve => {
        imgUtil.getOrientation(file).then(orient => {
          if (orient && orient !== '' && orient !== 1) {
            currentFile.url = '';

            const reader = new FileReader();
            const img = new Image();
            reader.onload = e => {
              img.src = e.target.result;
              img.onload = function() {
                const data = imgUtil.rotateImage(img, img.width, img.height, orient);
                const newFile = imgUtil.dataURLtoFile(data, file.name);

                currentFile.url = URL.createObjectURL(newFile);

                uploadFiles.splice(currentFileIndex, 1, currentFile);
                for (const p in newFile) {
                  if (Object.prototype.hasOwnProperty.call(newFile, p)) {
                    file[p] = newFile[p];
                  }
                }
                file.url = URL.createObjectURL(newFile);
                resolve(newFile);
              };
            };
            reader.readAsDataURL(file);
          } else {
            resolve(file);
          }
        });
      });
    },

    handelRemove(file) {
      const fileId = file.id;

      for (let index = this.fileList.length - 1; index >= 0; index--) {
        const element = this.fileList[index];

        if (element.id === fileId) {
          this.fileList.splice(index, 1);
        }
      }
    },

    handlePreview(file) {
      if (file.url) {
        this.dialogVisible = true;
        this.currentImg = file.url;
      }
    },
  },
};
</script>

<style lang="scss" scoped>
.preview-img {
  width: 100%;
}
</style>
